package com.hee.erp.modules.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.hee.erp.enums.AuditStatusEnum;
import com.hee.erp.enums.WorkflowNodeTypeEnum;
import com.hee.erp.enums.WorkflowUserTypeEnum;
import com.hee.erp.exception.BusinessException;
import com.hee.erp.filter.LoginContextHolder;
import com.hee.erp.modules.entity.*;
import com.hee.erp.modules.mapper.AuditFlowMapper;
import com.hee.erp.modules.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hee.erp.pojo.LoginInfo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author weizehong
 * @since 2022-05-18
 */
@Service
@Transactional
public class AuditFlowServiceImpl extends ServiceImpl<AuditFlowMapper, AuditFlow> implements IAuditFlowService {

    @Autowired
    IWf2RightService wf2RightService;

    @Autowired
    IWfMainService wfMainService;

    @Autowired
    ISysUserService sysUserService;

    @Autowired
    IAuditFlowService auditFlowService;

    @Autowired
    IAuditResultService auditResultService;

    @Override
    public void saveDetail(String routeMenu, String auditMainId) {
        //1、获取审批流id
        Wf2Right wf2Right = wf2RightService.getByRouteName(routeMenu);
        if (wf2Right == null) {
            throw new BusinessException("该模块未配置审批流");
        }
        //2、获取设置的审批流信息
        WfMain wfMain = wfMainService.getDetailById(wf2Right.getWfMainId());
        if (wfMain == null) {
            throw new BusinessException("审批流不存在");
        }

        //3、保存具体审批流信息
        if (wfMain.getNode() != null) {
            //保存第一个审批节点
            AuditFlow firstApproverAuditFlow = null;
            WfNode currentNode = wfMain.getNode();
            String parentId = "";
            if (currentNode.getNodeType().equals(WorkflowNodeTypeEnum.START)) {
                if (currentNode.getUserType().equals(WorkflowUserTypeEnum.SPECIFIED_PERSON)) {
                    //指定人员
                    if (!currentNode.getUserIds().contains(LoginContextHolder.get().getUserId())) {
                        throw new BusinessException("您不能发起此申请");
                    }
                }
            }

            //保存开始节点
            AuditFlow startAuditFlow = new AuditFlow();
            startAuditFlow.setAuditMainId(auditMainId);
            startAuditFlow.setParentId(parentId);
            startAuditFlow.setAuditorUserId(LoginContextHolder.get().getUserId());
            startAuditFlow.setAuditStatus(AuditStatusEnum.AUDITING);
            startAuditFlow.setAuditTime(LocalDateTime.now());
            startAuditFlow.setNodeType(currentNode.getNodeType());
            startAuditFlow.setNodeName(currentNode.getNodeName());
            auditFlowService.save(startAuditFlow);
            parentId = startAuditFlow.getId();
            currentNode = currentNode.getNext();
            AuditStatusEnum auditStatus = AuditStatusEnum.AUDITING;


            while (currentNode != null) {
                if (currentNode.getNodeType().equals(WorkflowNodeTypeEnum.APPROVER)) {
                    //审批人
                    AuditFlow parentNode = saveAuditFlowNode(currentNode, auditMainId, parentId,auditStatus);
                    auditStatus = AuditStatusEnum.DRAFT;
                    if (firstApproverAuditFlow == null) {
                        firstApproverAuditFlow = parentNode;
                        //更新t_audit_result中的audit_status,auditing_auditor_id
                        AuditResult auditResult = new AuditResult();
                        auditResult.setAuditStatus(firstApproverAuditFlow.getAuditStatus());
                        auditResult.setAuditingAuditorId(firstApproverAuditFlow.getAuditorUserId());
                        auditResultService.updateByMainId(auditResult, auditMainId);
                    }
                    parentId = parentNode.getId();
                } else if (currentNode.getNodeType().equals(WorkflowNodeTypeEnum.Copier)) {
                    //抄送人
                    saveAuditFlowNodeCopier(currentNode, auditMainId);
                }
                currentNode = currentNode.getNext();
            }

        } else {
            throw new BusinessException("该审批流未设置审批节点");
        }


    }

    private void saveAuditFlowNodeCopier(WfNode currentNode, String auditMainId) {
        List<SysUser> sysUserList = null;
        if (currentNode.getUserType().equals(WorkflowUserTypeEnum.SPECIFIED_PERSON)) {
            //指定人员
            List<String> userIds = currentNode.getUserIds();
            if (userIds != null && userIds.size() > 0) {
                sysUserList = sysUserService.listByIds(userIds);
            }
        } else if (currentNode.getUserType().equals(WorkflowUserTypeEnum.ALL_PEOPLE)) {
            //所有人员
            sysUserList = sysUserService.list();
        }

        if (sysUserList != null && sysUserList.size() > 0) {
            List<AuditFlow> list = sysUserList.stream().map(sysUser -> {
                AuditFlow auditFlow = new AuditFlow();
                auditFlow.setAuditMainId(auditMainId);
                auditFlow.setAuditorUserId(sysUser.getId());
                auditFlow.setAuditStatus(AuditStatusEnum.DRAFT);
                auditFlow.setNodeType(WorkflowNodeTypeEnum.Copier);

                return auditFlow;

            }).collect(Collectors.toList());
            auditFlowService.saveBatch(list);
        }
    }

    @Override
    public List<AuditFlow> listAuditNodeByMainId(String auditMainId) {
        LambdaQueryWrapper<AuditFlow> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AuditFlow::getAuditMainId, auditMainId);
        queryWrapper.eq(AuditFlow::getNodeType, WorkflowNodeTypeEnum.APPROVER);

        return this.list(queryWrapper);
    }

    @Override
    public AuditFlow getAuditingUserByMainId(String auditMainId) {
        LambdaQueryWrapper<AuditFlow> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AuditFlow::getAuditMainId, auditMainId);
        queryWrapper.eq(AuditFlow::getAuditStatus, AuditStatusEnum.AUDITING);
        queryWrapper.eq(AuditFlow::getNodeType, WorkflowNodeTypeEnum.APPROVER);

        return this.getOne(queryWrapper);
    }

    @Override
    public void audit(AuditFlow auditFlow) {
        this.updateById(auditFlow);
        AuditResult auditResult = new AuditResult();
        if (auditFlow.getAuditStatus().equals(AuditStatusEnum.PASS)) {
            //审批通过,寻找下一个审核人
            AuditFlow nowAuditFlow = this.getById(auditFlow.getId());
            AuditFlow nextAuditFlow = this.getByParentId(nowAuditFlow.getId());

            if (nextAuditFlow != null) {
                nextAuditFlow.setAuditStatus(AuditStatusEnum.AUDITING);
                this.updateById(nextAuditFlow);

                //更新t_audit_result
                auditResult.setAuditStatus(nextAuditFlow.getAuditStatus());
                auditResult.setAuditingAuditorId(nextAuditFlow.getAuditorUserId());
            } else {
                //更新t_audit_result
                auditResult.setAuditStatus(AuditStatusEnum.PASS);
                auditResult.setAuditingAuditorId(auditFlow.getAuditorUserId());

                auditResult.setAuditTime(LocalDateTime.now());
                auditResult.setAuditRemark(auditFlow.getAuditRemark());

            }
        } else if (auditFlow.getAuditStatus().equals(AuditStatusEnum.REJECT)) {
            //审批拒绝
            //更新t_audit_result
            auditResult.setAuditStatus(AuditStatusEnum.REJECT);
            auditResult.setAuditingAuditorId(auditFlow.getAuditorUserId());

            auditResult.setAuditTime(LocalDateTime.now());
            auditResult.setAuditRemark(auditFlow.getAuditRemark());

        }

        auditResultService.updateByMainId(auditResult, auditFlow.getAuditMainId());
    }

    @Override
    public AuditFlow getByParentId(String parentId) {
        LambdaQueryWrapper<AuditFlow> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AuditFlow::getParentId, parentId);
        return this.getOne(queryWrapper);
    }

    @Override
    public AuditFlow getStartNodeByMainId(String auditMainId) {
        LambdaQueryWrapper<AuditFlow> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AuditFlow::getAuditMainId, auditMainId);
        queryWrapper.eq(AuditFlow::getNodeType, WorkflowNodeTypeEnum.START);

        return this.getOne(queryWrapper);
    }

    private AuditFlow saveAuditFlowNode(WfNode node, String auditMainId, String parentId,AuditStatusEnum auditStatus) {
        AuditFlow auditFlow = new AuditFlow();
        auditFlow.setAuditMainId(auditMainId);
        auditFlow.setParentId(parentId);
        auditFlow.setAuditStatus(auditStatus);
        auditFlow.setNodeType(WorkflowNodeTypeEnum.APPROVER);
        auditFlow.setNodeName(node.getNodeName());

        //1、保存审批流节点
        //@ApiModelProperty("-1:未设置，0:任何人,1:直接上级，2：指定人员")
        if (node.getUserType().equals(WorkflowUserTypeEnum.NOT_SETTING)) {
            throw new BusinessException("审批节点未设置审批人");
        }
        if (node.getUserType().equals(WorkflowUserTypeEnum.ALL_PEOPLE)) {
            throw new BusinessException("审批节点不能为所有人");
        }

        LoginInfo loginInfo = LoginContextHolder.get();
        SysUser currentUser = sysUserService.getById(loginInfo.getUserId());
        if (node.getUserType().equals(WorkflowUserTypeEnum.DIRECT_SUPERIOR)) {
            //直接上级
            //1、获取直接上级
            if (StringUtils.isBlank(currentUser.getParentId())) {
                throw new BusinessException("该用户没有配置直接上级");
            }
            SysUser parentUser = sysUserService.getById(currentUser.getParentId());
            if (parentUser == null) {
                throw new BusinessException("该用户直接上级不存在");
            }

            //2、保存审批流节点
            auditFlow.setAuditorUserId(parentUser.getId());
        } else if (node.getUserType().equals(WorkflowUserTypeEnum.INDIRECT_SUPERIOR)) {
            //间接上级
            //1、获取间接上级
            if (StringUtils.isBlank(currentUser.getParentId())) {
                throw new BusinessException("该用户没有配置直接上级");
            }
            SysUser parentUser = sysUserService.getById(currentUser.getParentId());
            if (parentUser == null) {
                throw new BusinessException("该用户直接上级不存在");
            }
            //2、获取间接上级
            if (StringUtils.isBlank(parentUser.getParentId())) {
                throw new BusinessException("该用户没有配置间接上级");
            }
            SysUser grandUser = sysUserService.getById(parentUser.getParentId());
            if (grandUser == null) {
                throw new BusinessException("该用户间接上级不存在");
            }

            //3、保存审批流节点
            auditFlow.setAuditorUserId(grandUser.getId());
        } else if (node.getUserType().equals(WorkflowUserTypeEnum.SPECIFIED_PERSON)) {
            //指定人员
            if (node.getUserIds() == null || node.getUserIds().size() == 0) {
                throw new BusinessException("审批节点指定人员不能为空");
            }
            for (String userId : node.getUserIds()) {
                //1、保存审批流节点
                SysUser specifiedUser = sysUserService.getById(userId);
                if (specifiedUser == null) {
                    throw new BusinessException("指定人员不存在");
                }
                auditFlow.setAuditorUserId(specifiedUser.getId());

            }
        } else {
            throw new BusinessException("审批节点未设置审批人");
        }
        auditFlowService.save(auditFlow);
        return auditFlow;

    }
}
